{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "预测用户对item的打分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import pickle as pk\n",
    "import matplotlib.pyplot as plt\n",
    "#字典，用于建立用户和物品的索引\n",
    "from collections import defaultdict\n",
    "#稀疏矩阵，存储打分表\n",
    "import scipy.io as sio\n",
    "import scipy.sparse as ss\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "data_path = './Data/'\n",
    "model_path = './model/'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 用户和 item 的索引\n",
    "with open(model_path+'train_users_index.pkl', 'rb') as fr:\n",
    "    users_index = pk.load(fr)\n",
    "fr.close()\n",
    "\n",
    "with open(model_path+'train_items_index.pkl', 'rb') as fr:\n",
    "    items_index = pk.load(fr)\n",
    "fr.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'dict'>\n"
     ]
    }
   ],
   "source": [
    "print(type(users_index))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 计算用户 uid 对 iid 的预测得分\n",
    "def user_cf_pred(uid, iid):\n",
    "    sim_accumulate=0.0\n",
    "    rat_acc=0.0\n",
    "    for user_id in item_users[iid]: # 对item打过分的所有用户\n",
    "        # 从用户相似度矩阵取得 user_id 和 uid 之间的相似度\n",
    "        sim = user_similarity_matrix[user_id,uid]\n",
    "        if sim != 0:\n",
    "            rat_acc += sim*(user_item_scores[user_id,iid]-user_mean_score[user_id])\n",
    "            sim_accumulate += np.abs(sim)\n",
    "    if sim_accumulate != 0:\n",
    "        score = user_mean_score[uid] + rat_acc/sim_accumulate\n",
    "    else:\n",
    "        score = user_mean_score[uid]\n",
    "    \n",
    "    return score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(model_path+'data_test_temp1.pkl', 'rb') as fr:\n",
    "    data_test_temp1 = pk.load(fr)\n",
    "fr.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.series.Series'>\n",
      "id                                                    0\n",
      "msno       V8ruy7SGk7tDm3zA51DPpn6qutt+vmKMBKa21dp54uM=\n",
      "song_id    WmHKgKMlp1lQMecNdNvDMkvIycZYHnFwDT72I5sIssc=\n",
      "Name: 0, dtype: object\n"
     ]
    }
   ],
   "source": [
    "print(type(data_test_temp1.loc[0,:]))\n",
    "print(data_test_temp1.loc[0,:])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_test_score(line):\n",
    "    msno = line.msno\n",
    "    song_id = line.song_id\n",
    "    pre_score = 0\n",
    "    if (msno not in users_index) or (song_id not in items_index):\n",
    "        if msno not in users_index:\n",
    "            print('msno is new: %s' % msno)\n",
    "        if song_id not in items_index:\n",
    "            print('song_id is new: %s' % song_id)\n",
    "        return pre_score\n",
    "    cur_user_index = users_index[msno]\n",
    "    cur_item_index = items_index[song_id]\n",
    "    pre_score = user_cf_pred(cur_user_index, cur_item_index)\n",
    "    pre_score = pre_score - 1\n",
    "    if pre_score < 0:\n",
    "        pre_score = 0\n",
    "    if pre_score > 1:\n",
    "        pre_score = 1\n",
    "    return pre_score\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "data_test_temp1['target'] = data_test_temp1.apply(lambda line : get_test_score(line))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将打分结果转为 csv 文件\n",
    "result_df = data_test_temp1.loc[:,['id','target']]\n",
    "result_df.to_csv(data_path+'user_cf_result.csv', index = False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用 user_based_cf 做音乐推荐的过程中，遇到的最大问题是最后算到的用户相似度矩阵太大，自己的电脑内存处理不了，\n",
    "导致后续的计算无法进行。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
